/*
 * WRITTEN BY: Thomas Jakway
 * Project GLOnHill
 * http://code.google.com/p/gl-on-hill/
 * anonymous SVN checkout:
 * svn checkout http://gl-on-hill.googlecode.com/svn/trunk/ gl-on-hill-read-only
 * 
 * Demonstrates drawing an effects-filled scene in C++ with OpenGL
 * Textures are fetched for educational purposes only
 *
 *
 * Licensed under the GNU GPL v3, available from http://www.gnu.org/licenses/gpl-3.0.txt
 */


//global includes
#ifndef GLOBAL
#include "global.h"
#endif

//uses SDL, a cross-platform method of getting an SDL context
#include <SDL.h>

//OpenGL headers
#ifdef MAC_OS_X
#include <OpenGL/OpenGL.h>
#include <OpenGL/glu.h>
#endif

#ifdef LINUX
#include <GL/gl.h>
#include <GL/glu.h>
#endif

//C functions we need
#include <stdio.h>
#include <stdlib.h>
//need time for seeding the random function
#include <time.h>

//draw file
#ifndef DRAW
#include "draw.h"
#endif

//initialization and resize function
#ifndef RESIZE_AND_INIT
#include "resize_and_init.h"
#endif

#ifndef STAR
#include "Star.h"
#endif

//C++ i/o streams
#include <iostream>
#include <fstream>
using namespace std;


/* screen width, height, and bit depth */
#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP     16

/* Define our booleans */
#define TRUE  true
#define FALSE false

/* This is our SDL surface */
SDL_Surface *surface;

//store user input
float userrotatex = 0;
float userrotatey = 0;
float userrotatez = 0;

float usertranslatex = 0;
float usertranslatey = 0;
float usertranslatez = 0;

//function prototypes
void Quit(int);
void handleKeyPress(SDL_keysym);

//DEBUGGING ONLY!
void DEBUG_PRINT_USER_TRANSFORMATIONS();






/* function to release/destroy our resources and restoring the old desktop */
void Quit( int returnCode )
{
	//delete the texture Star allocated for itself
	Star::deleteStarTexture();
	
	//delete all created textures
	glDeleteTextures(SIZE_OF_TEX_ARRAY, tex_id);

	//disable client states
	glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);


    /* clean up the window */
    SDL_Quit( );

    /* and exit appropriately */
    exit( returnCode );
}


ofstream printStream("transformations.txt", ios::trunc);
void printTransformations()
{
	printStream << "TRANSLATIONS:  " << usertranslatex << "  " << usertranslatey
	<< "  " << usertranslatez << endl
	<< "ROTATIONS:  " << userrotatex << "  " << userrotatey << "  " << userrotatez << endl
	<< endl;
}

#define CHANGEAMOUNT 3

/* function to handle key press events */
void handleKeyPress( SDL_keysym *keysym )
{
    switch ( keysym->sym )
	{
	case SDLK_ESCAPE:
	    /* ESC key was pressed */
	    Quit( 0 );
	    break;
	case SDLK_F1:
	    /* F1 key was pressed
	     * this toggles fullscreen mode
	     */
	    SDL_WM_ToggleFullScreen( surface );
	    break;
    case SDLK_w:
        usertranslatez = usertranslatez + CHANGEAMOUNT;
        break;
    case SDLK_s:
        usertranslatez = usertranslatez - CHANGEAMOUNT;
        break;
    case SDLK_a:
        usertranslatex = usertranslatex + CHANGEAMOUNT;
        break;
    case SDLK_d:
        usertranslatex = usertranslatex - CHANGEAMOUNT;
        break;

    //FOR DEBUGGING:
    case SDLK_r:
        usertranslatey = usertranslatey - CHANGEAMOUNT;
        break;
    case SDLK_f:
        usertranslatey = usertranslatey + CHANGEAMOUNT;
        break;

    case SDLK_UP:
        userrotatex = userrotatex + CHANGEAMOUNT;
        break;
    case SDLK_DOWN:
        userrotatex = userrotatex - CHANGEAMOUNT;
        break;
    case SDLK_RIGHT:
        userrotatey = userrotatey + CHANGEAMOUNT;
        break;
    case SDLK_LEFT:
        userrotatey = userrotatey - CHANGEAMOUNT;
        break;
	


    //DEBUGGING ONLY!
    case SDLK_p:
		printTransformations();
        break;

	default:
	    break;
	}

    return;
}

void DEBUG_PRINT_USER_TRANSFORMATIONS()
{
    cout << "userrotatex is: " << userrotatex << endl
         << "userrotatey is: " << userrotatey << endl
         << "userrotatez is: " << userrotatez << endl
            << endl
        << "usertranslatex is: " << usertranslatex << endl
        << "usertranslatey is: " << usertranslatey << endl
        << "usertranslatez is: " << usertranslatez << endl;
}





int main( int argc, char **argv )
{
    /* Flags to pass to SDL_SetVideoMode */
    int videoFlags;
    /* main loop variable */
    int done = FALSE;
    /* used to collect events */
    SDL_Event event;
    /* this holds some info about our display */
    const SDL_VideoInfo *videoInfo;
    /* whether or not the window is active */
    int isActive = TRUE;

    /* initialize SDL */
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
	{
	    fprintf( stderr, "Video initialization failed: %s\n",
		     SDL_GetError( ) );
	    Quit( 1 );
	}

    /* Fetch the video info */
    videoInfo = SDL_GetVideoInfo( );

    if ( !videoInfo )
	{
	    fprintf( stderr, "Video query failed: %s\n",
		     SDL_GetError( ) );
	    Quit( 1 );
	}

    /* the flags to pass to SDL_SetVideoMode */
    videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
    videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
    videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
    videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */

    /* This checks to see if surfaces can be stored in memory */
    if ( videoInfo->hw_available )
	videoFlags |= SDL_HWSURFACE;
    else
	videoFlags |= SDL_SWSURFACE;

    /* This checks if hardware blits can be done */
    if ( videoInfo->blit_hw )
	videoFlags |= SDL_HWACCEL;

    /* Sets up OpenGL double buffering */
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

    /* get a SDL surface */
    surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
				videoFlags );

    /* Verify there is a surface */
    if ( !surface )
	{
	    fprintf( stderr,  "Video mode set failed: %s\n", SDL_GetError( ) );
	    Quit( 1 );
	}

    /* initialize OpenGL */
    if(initialize_OpenGL() != true)
    {
    	cout << "ERROR" << endl;
    }

    /* resize the initial window */
    resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );

    /* wait for events */
    while ( !done )
	{
	    /* handle the events in the queue */

	    while ( SDL_PollEvent( &event ) )
		{
		    switch( event.type )
			{
			case SDL_ACTIVEEVENT:
			    /* Something's happend with our focus
			     * If we lost focus or we are iconified, we
			     * shouldn't draw the screen
			     */
			    if ( event.active.gain == 0 )
				isActive = FALSE;
			    else
				isActive = TRUE;
			    break;
			case SDL_VIDEORESIZE:
			    /* handle resize event */
			    surface = SDL_SetVideoMode( event.resize.w,
							event.resize.h,
							16, videoFlags );
			    if ( !surface )
				{
				    fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
				    Quit( 1 );
				}
			    resizeWindow( event.resize.w, event.resize.h );
			    break;
			case SDL_KEYDOWN:
			    /* handle key presses */
			    handleKeyPress( &event.key.keysym );
			    break;
			case SDL_QUIT:
			    /* handle quit requests */
			    done = TRUE;
			    break;
			default:
			    break;
			}
		}

	    /* draw the scene */
	    if ( isActive )
		draw();
	}

    /* clean ourselves up and exit */
    Quit( 0 );

    /* Should never get here */
    return( 0 );
}
